package com.carkeeper.search.service.impl;

import com.alibaba.fastjson.JSON;
import com.carkeeper.pojo.ServiceInfo;
import com.carkeeper.search.service.ServiceSearchService;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author pengjinxiong
 * @version 1.0
 * @date 2020/11/25 9:20
 */
//服务目录全文检索
@Service
public class ServiceSearchServiceImpl implements ServiceSearchService {
    //使用springdataelasticsearch技术进行全文检索
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @Override
    public Map searchQuery(Map<String, String> searchMap) {
        Map<String, Object> resultMap = new HashMap<>();
        //第一个功能：根据关键字搜索
        if (searchMap != null) {
            //1， 创建
            NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
            //2. 构建boolQuery对象
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
            //2.1 按照服务商名称搜索
            if (StringUtils.isNotEmpty(searchMap.get("storeName"))) {
                boolQuery.must(QueryBuilders.matchQuery("storeName", searchMap.get("storeName")).operator(Operator.AND));
            }
          //编码
            if (StringUtils.isNotEmpty(searchMap.get("code"))) {
                boolQuery.must(QueryBuilders.termQuery("code", searchMap.get("code")));
            }
            //服务名称
             if (StringUtils.isNotEmpty(searchMap.get("serviceName"))) {
                boolQuery.must(QueryBuilders.matchQuery("serviceName", searchMap.get("serviceName")));
            }
            //服务分类
           if (StringUtils.isNotEmpty(searchMap.get("serviceType"))) {
                boolQuery.must(QueryBuilders.termQuery("serviceType", searchMap.get("serviceType")));
            }

            //3.添加查询条件
            nativeSearchQueryBuilder.withQuery(boolQuery);


            //3.1 分类聚合查询
            //定义分类聚合名称,目的是为了根据serviceType去查询
            String serviceType="serviceType";
            nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms(serviceType).field("serviceType"));

            //3.2 分页查询
            String pageNum = searchMap.get("pageNum");
            String pageSize = searchMap.get("pageSize");
            if(pageNum==null){
                pageNum="1";
            }
            if(pageSize==null){
                pageSize="15";
            }
            nativeSearchQueryBuilder.withPageable(PageRequest.of(Integer.parseInt(pageNum)-1,Integer.parseInt(pageSize)));
            //4.执行查询，返回结果
            AggregatedPage<ServiceInfo> serviceInfos = elasticsearchTemplate.queryForPage(nativeSearchQueryBuilder.build(), ServiceInfo.class, new SearchResultMapper() {
                @Override
                public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) {
                    //创建一个List集合用来承载搜索出来的结果
                    List list = new ArrayList();

                    //获取命中结果
                    SearchHits hits = searchResponse.getHits();
                    if (hits != null) {
                        for (SearchHit hit : hits) {
                            //把每个命中数据转化成serviceinfo对象
                            ServiceInfo serviceInfo = JSON.parseObject(hit.getSourceAsString(), ServiceInfo.class);
                            //添加到list集合中
                            list.add(serviceInfo);
                        }
                    }
                    /**
                     * 参数1表示搜索结果list
                     * 参数2表示分页对象
                     * 参数3表示获取命中结果总记录数
                     * 参数4表示响应的聚合查询
                     */
                    return new AggregatedPageImpl<>(list, pageable, hits.getTotalHits(), searchResponse.getAggregations());
                }
            });
            //5.数据封装
            resultMap.put("total", serviceInfos.getTotalElements());//总记录数
            resultMap.put("totalPages", serviceInfos.getTotalPages());//总页数
            resultMap.put("serviceList", serviceInfos.getContent());//数据列表
            //获取分类聚合结果
            StringTerms typeTerms = (StringTerms) serviceInfos.getAggregation(serviceType);
            List<String> typeList = typeTerms.getBuckets().stream().map(bucket -> bucket.getKeyAsString()).collect(Collectors.toList());
            resultMap.put("typeList",typeList);
            //当前页码
            resultMap.put("pageNum",pageNum);
            return resultMap;
        }
        return null;

    }


}
